package com.lixiaoyi.controller;

import com.lixiaoyi.config.redis.RedisService;
import com.lixiaoyi.entity.Permission;
import com.lixiaoyi.entity.User;
import com.lixiaoyi.entity.UserInfo;
import com.lixiaoyi.utils.JwtUtils;
import com.lixiaoyi.utils.MenuTree;
import com.lixiaoyi.utils.Result;
import com.lixiaoyi.vo.RouterVo;
import com.lixiaoyi.vo.TokenVo;
import io.jsonwebtoken.Jwts;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author 李小毅
 * @Description
 * @Date 2022-07-02
 */

@RestController
@RequestMapping("/api/sysUser")
public class SysUserController {


    @Resource
    private JwtUtils jwtUtils;

    @Resource
    private RedisService redisService;


    /**
     * 刷新token
     * @param request
     * @return
     */
    @PostMapping("/refreshToken")
    public Result refreshToken(HttpServletRequest request){

        // 从header中获取前端提交的token
        String token = request.getHeader("token");
        // 如果header中没有token 则从参数中获取
        if (ObjectUtils.isEmpty(token)){
            token = request.getParameter("token");
        }

        // 从Spring Security上下文获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 获取身份信息
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        // 重新生成新的token
        String newToken = "";
        // 验证原来的token是否合法
        if (jwtUtils.validateToken(token,userDetails)){
            // 生成新的token
            newToken = jwtUtils.refreshToken(token);
        }
        // 获取本次token的到期时间 并交给前端判断
        long expireTime = Jwts.parser().setSigningKey(jwtUtils.getSecret())
                .parseClaimsJws(newToken.replace("jwt_", ""))
                .getBody().getExpiration().getTime();

        // 清除原来的token信息
        String oldTokenKey = "token_" + token;
        redisService.del(oldTokenKey);
        // 存储新的token 到缓存中
        String newTokenKey = "token_" + newToken;
        redisService.set(newTokenKey, newToken,jwtUtils.getExpiration() / 1000);
        // 创建TokenVo对象
        TokenVo tokenVo = new TokenVo(expireTime,newToken);
        // 返回数据
        return Result.ok(tokenVo).message("token生成成功");
    }

    @GetMapping("/getInfo")
    public Result getInfo(){

        // 从Spring Security 上下文获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 判断authentication对象 是否为空
        if (authentication == null){
            return Result.error().message("用户信息查询失败");
        }

        // 获取用户信息
        User user = (User)authentication.getPrincipal();
        // 用户权限集合
        List<Permission> permissionList = user.getPermissionList();
        // 获取角色权限编码字段
        Object[] roles = permissionList.stream()
                .filter(Objects::nonNull)
                .map(Permission::getCode)
                .toArray();

        // 创建用户信息对象
        UserInfo userInfo = new UserInfo(user.getId(),user.getNickName(),user.getAvatar(),
                null,roles);
        // 返回数据
        return Result.ok(userInfo).message("用户查询成功");


    }


    /**
     * 获取菜单数据
     * @return
     */
    @GetMapping("/getMenuList")
    public Result getMenuList(){
        // 从Spring Security 上下文获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 获取用户信息
        User user = (User)authentication.getPrincipal();
        // 用户权限集合
        List<Permission> permissionList = user.getPermissionList();
        // 筛选目录和菜单
        List<Permission> collect = permissionList.stream()
                .filter(item -> item != null && item.getType() != 2)
                .collect(Collectors.toList());
        // 生成路由数据
        List<RouterVo> routerVoList = MenuTree.makeRouter(collect,0L);
        // 返回数据
        return Result.ok(routerVoList).message("菜单数据获取成功");

    }


    @PostMapping("/logout")
    public Result logout(HttpServletRequest request, HttpServletResponse response){

        // 获取token信息
        String token = request.getHeader("token");
        // 如果头部中没有携带token 则从参数中获取
        if (ObjectUtils.isEmpty(token)){
            //从参数中获取token
            token =  request.getParameter("token");
        }
        // 从Spring Security上下文中获取用户对象
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 判断用户信息是否为空 如果不空 则需要清空用户数据
        if (authentication !=null ){
            // 清空用户信息
            new SecurityContextLogoutHandler().logout(request,response,authentication);
            // 清楚redis缓存中的token
            redisService.del("token_" + token);
            return Result.ok().message("用户退出成功");

        }

        return Result.error().message("用户退出失败");

    }

}
